package fun.easycode.jointblock.core;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Builder;
import lombok.Data;
import org.springframework.http.ResponseEntity;

import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 分页结果返回dto封装
 * @author xuzhe
 */
@Data
@Builder
public class PageDto<T> {
    private Long current;
    private Long size;
    private Long totalSize;
    private Long totalPage;
    private List<T> data;

    /**
     * mybatis-plus page转换PageDto
     * @param page mybatis plus page
     * @param convert 转换关系
     * @param <T> dto类型
     * @param <K> 实体类型
     * @return PageDto
     */
    public static <T,K> PageDto<T> toPageDto(Page<K> page, Convert<K,T> convert){

        List<T> data = page.getRecords().stream().map(convert::convert)
                .collect(Collectors.toList());
        return PageDto.<T>builder()
                .current(page.getCurrent())
                .size(page.getSize())
                .totalSize(page.getTotal())
                .totalPage(page.getPages())
                .data(data)
                .build();
    }

    /**
     * 根据ResponseEntity 返回值以及qry生成PageDto
     * @param qry
     * @param entity
     * @param convert
     * @return
     * @param <T>
     * @param <K>
     * @param <L>
     */
    public static <T,K,L extends Collection<K>> PageDto<T> toPageDto(PagingQry qry, ResponseEntity<L> entity, Convert<K,T> convert){

        List<T> data = Objects.requireNonNull(entity.getBody())
                .stream().map(convert::convert).collect(Collectors.toList());

        return PageDto.<T>builder()
                .current(Long.valueOf(qry.getCurrent()))
                .totalPage(getHeaderValue(Constant.TOTAL_PAGE_HEADER, entity, 0L, Long.class))
                .totalSize(getHeaderValue(Constant.TOTAL_SIZE_HEADER, entity, 0L, Long.class))
                .size(Long.valueOf(qry.getSize()))
                .data(data)
                .build();
    }

    /**
     * 根据ResponseEntity 返回值生成PageDto
     * @param entity
     * @param convert
     * @return
     * @param <T>
     * @param <K>
     * @param <L>
     */
    public static <T,K,L extends Collection<K>> PageDto<T> toPageDto(ResponseEntity<L> entity, Convert<K,T> convert){

        List<T> data = Objects.requireNonNull(entity.getBody())
                .stream().map(convert::convert).collect(Collectors.toList());

        return PageDto.<T>builder()
                .current(getHeaderValue(Constant.CURRENT_HEADER, entity, 1L, Long.class))
                .totalPage(getHeaderValue(Constant.TOTAL_PAGE_HEADER, entity, 0L, Long.class))
                .totalSize(getHeaderValue(Constant.TOTAL_SIZE_HEADER, entity, 0L, Long.class))
                .size(getHeaderValue(Constant.SIZE_HEADER, entity, 10L, Long.class))
                .data(data)
                .build();
    }

    /**
     * 获取header通用封装方法
     * @param header
     * @param responseEntity
     * @param defaultValue
     * @param type
     * @return
     * @param <T>
     */
    private static <T> T getHeaderValue(String header, ResponseEntity responseEntity, T defaultValue, Class<T> type){

        return Optional.ofNullable(responseEntity.getHeaders().get(header))
                .map(headers-> cn.hutool.core.convert.Convert.convert(type, headers.get(0)))
                .orElse(defaultValue);
    }

    /**
     * 转换，这是mybatis plus page类型和dto类型转换的声明
     * @param <T>
     * @param <K>
     */
    @FunctionalInterface
    public interface Convert<T,K>{
        K convert(T t);
    }
}